﻿// --------------
// 作者:Vitity
// --------------

using NICWebApi.Extensions.RESTfulResult.Internal;

namespace NICWebApi.Extensions.RESTfulResult.Filter;

/// <summary>
/// Swagger自定义操作过滤器
/// </summary>
public class SwaggerOperationFilter : IOperationFilter
{
    // 定义一个ISchemaGenerator类型的私有字段，用于生成Schema
    private readonly ISchemaGenerator _schemaGenerator;

    /// <summary>
    ///
    /// </summary>
    /// <param name="schemaGenerator"></param>
    public SwaggerOperationFilter(ISchemaGenerator schemaGenerator)
    {
        _schemaGenerator = schemaGenerator;
    }

    /// <summary>
    /// 实现IOperationFilter接口的Apply方法，用于自定义Swagger文档的生成
    /// </summary>
    /// <param name="operation"></param>
    /// <param name="context"></param>
    public void Apply(OpenApiOperation operation, OperationFilterContext context)
    {
        // 获取当前操作返回的类型
        var returnType = context.MethodInfo.ReturnType;

        // 如果类标注了NotRESTfulResult，则不处理
        if (returnType.IsDefined(typeof(NotRESTfulResult), true)) return;

        // 如果方法标注了NotRESTfulResult，则不处理
        if (context.MethodInfo.IsDefined(typeof(NotRESTfulResult), true)) return;

        // 如果返回类型是Task,会读取所有属性导致卡顿【2025-03-17】
        if (returnType == typeof(Task) || returnType == typeof(void)) return;
         
        // 如果返回类型是Task<>，则获取Task<>中的泛型类型
        if (returnType.IsGenericType && returnType.GetGenericTypeDefinition() == typeof(Task<>))
        {
            returnType = returnType.GetGenericArguments()[0];
        }

        // 如果返回类型是ActionResult<>，则获取ActionResult<>中的泛型类型
        if (returnType.IsGenericType && returnType.GetGenericTypeDefinition() == typeof(ActionResult<>))
        {
            returnType = returnType.GetGenericArguments()[0];
        }

        // 创建一个RESTfulResult<>的泛型类型，其中泛型参数为当前操作的返回类型
        var type = typeof(RESTfulResult<>).MakeGenericType(returnType);

        // 使用_schemaGenerator生成Schema，并将其添加到SchemaRepository中
        var schema = _schemaGenerator.GenerateSchema(type, context.SchemaRepository);

        // 清空当前操作的所有响应
        operation.Responses.Clear();

        // 添加一个200响应，描述为统一的成功响应，并设置其内容类型为application/json，Schema为生成的Schema
        operation.Responses.Add("200", new OpenApiResponse
        {
            Description = "",
            Content = new Dictionary<string, OpenApiMediaType>
            {
                ["application/json"] = new OpenApiMediaType
                {
                    Schema = schema,
                }
            }
        });
    }
}